home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / c / cshell / comm3.c < prev    next >
C/C++ Source or Header  |  1994-03-19  |  55KB  |  2,732 lines

  1. /*
  2.  * COMM3.C
  3.  *
  4.  * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
  5.  * Version 5.00L by Urban Mueller 17-Feb-91
  6.  * Version 5.20L by Andreas M. Kirchwitz (Fri, 13 Mar 1992)
  7.  *
  8.  */
  9.  
  10. #include "shell.h"
  11.  
  12. /* comm3.c */
  13. static void doassign(char *log, char *phy);
  14. static void assignlist(void);
  15. static int strings_in_file(long mask, char *s, char *path);
  16. static int htype_a_file   (long mask, char *s, char *path);
  17. static void install_menu(char **mav, int mac);
  18. static int line_filter( char *(*line)(char *) );
  19.  
  20.  
  21. /* Casting conveniences */
  22. #define BPTR_TO_C(strtag, var)  ((struct strtag *)(BADDR( (ULONG) var)))
  23. #define PROC(task)              ((struct Process *)task)
  24. #define CLI(proc)               (BPTR_TO_C(CommandLineInterface, proc->pr_CLI))
  25.  
  26.  
  27. int do_ln(void)
  28. {
  29.     char *linkname;
  30.     long link_type;
  31.     long dest_data;
  32.     BOOL success;
  33.  
  34.     if( ac!=2 && ac!=3 ) {
  35.         show_usage( NULL );
  36.         return 20;
  37.     }
  38.  
  39.     if (ac==2)
  40.         linkname = FilePart(av[1]);
  41.     else
  42.         linkname = av[2];
  43.  
  44.     if (options&1) {
  45.         link_type = LINK_SOFT;
  46.         dest_data = (long)av[1];
  47.     }
  48.     else {
  49.         link_type = LINK_HARD;
  50.         if (!( dest_data = (long)Lock(av[1],ACCESS_READ) )) {
  51.             pError(av[1]);
  52.             return 20;
  53.         }
  54.     }
  55.  
  56.     success = MakeLink(linkname,dest_data,link_type);
  57.  
  58.     if (link_type==LINK_HARD)
  59.         UnLock((BPTR)dest_data);
  60.  
  61.     if (!success) {
  62.         pError(linkname);
  63.         return 20;
  64.     }
  65.  
  66.     return 0;
  67. }
  68.  
  69.  
  70. do_tee( void )
  71. {
  72.     char buf[256];
  73.     FILE *out;
  74.  
  75.     prepscroll( ac==1 );
  76.     if( ac>2 ) { ierror( av[2], 500 ); return 20; }
  77.     if( ac==1 ) out=stderr;
  78.     else if( !(out=fopen( av[1], "w" ))) { pError( av[1] ); return 20; }
  79.     while (safegets(buf,stdin)) {
  80.         puts(buf);
  81.         quickscroll();
  82.         fprintf(out,"%s\n",buf);
  83.     }
  84.     if( ac!=1 ) fclose( out );
  85.     return 0;
  86. }
  87.  
  88. do_head( char *garbage, int com )
  89. {
  90.     FILE *f;
  91.     int i, n = 10;
  92.     char buf[256];
  93.  
  94.     if (ac==1) {                    /* use stdin */
  95.         f = stdin;
  96.     }
  97.     else {
  98.         f=fopen(av[1],"r");
  99.         if (f==NULL) {
  100.             if (ac==2 && isnum(av[1])) {    /* use stdin */
  101.                 f = stdin;
  102.                 n = atol(av[1]);
  103.             }
  104.             else {
  105.                 pError(av[1]);
  106.                 return 20;
  107.             }
  108.         }
  109.     }
  110.  
  111.     if (ac>2) {
  112.         if (!isnum(av[2])) {   /* AMK: IoErr() replaced by isnum() */
  113.             ierror(av[2],511);
  114.             return 20;
  115.         }
  116.         n=(int)atol(av[2]);
  117.     }
  118.  
  119.     if (com) {    /* tail specific part */
  120.         i=0;
  121.         while (fgets(buf, 256, f) && ! dobreak()) i++;
  122.         rewind(f);
  123.         if (n>i) n=i;
  124.         i=i-n;
  125.         while (i-- && fgets(buf, 256, f) && ! dobreak()) ;
  126.     }
  127.  
  128.     for (i=1; i<=n && fgets(buf, 256, f) && ! dobreak(); i++)
  129.         printf("%s", buf);
  130.  
  131.     if (f!=stdin)
  132.         fclose(f);
  133.  
  134.     return 0;
  135. }
  136.  
  137. #if 0
  138. do_head( char *garbage, int com )
  139. {
  140.     int i, n;
  141.     FILE *f;
  142.     char buf[256];
  143.  
  144.     if (ac>2) {
  145.         if (!isnum(av[2])) {   /* AMK: IoErr() replaced by isnum() */
  146.             ierror(av[2],511);
  147.             return 20;
  148.         }
  149.         n=(int)atol(av[2]);
  150.     } else n=10;
  151.  
  152.     f=fopen(av[1], "r");
  153.     if (f==NULL) {
  154.         pError(av[1]);
  155.         return 20;
  156.     }
  157.     if (com) {    /* tail specific part */
  158.         i=0;
  159.         while (fgets(buf, 256, f) && ! dobreak()) i++;
  160.         rewind(f);
  161.         if (n>i) n=i;
  162.         i=i-n;
  163.         while (i-- && fgets(buf, 256, f) && ! dobreak()) ;
  164.     }
  165.     for (i=1; i<=n && fgets(buf, 256, f) && ! dobreak(); i++)
  166.         printf("%s", buf);
  167.     fclose(f);
  168.     return 0;
  169. }
  170. #endif
  171.  
  172. static int
  173. exword( char **src, char *buf )
  174. {
  175.     *buf=0;
  176.     if( **src==0 ) return 0;
  177.     while( **src && **src!=0xA0 )
  178.         *buf++=*(*src)++;
  179.     *buf=0;
  180.     if( **src ) (*src)++;
  181.     return 1;
  182. }
  183.  
  184. static char helpfound=0;
  185.  
  186. void
  187. man (FILE *f, char *s)
  188. {
  189.     char buf[140], entry[100];
  190.     int  len = sprintf (entry, "    %s", s);
  191.     char *example = "    ";
  192.  
  193.     prepscroll (0);
  194.     rewind (f);
  195.     do {                        /* look for required argument */
  196.         if (fgets (buf, sizeof(buf), f)==NULL || dobreak())
  197.             return;                /* GMD */
  198.     } while (strnicmp (entry, buf, len)) ;
  199.     helpfound = 1;
  200.  
  201.     do {                /* display help */
  202.         if (dobreak())
  203.             return;
  204.         quickscroll ();
  205.         printf ("%s", buf);
  206.         if (fgets (buf, sizeof(buf), f) == NULL)
  207.             return;
  208.     } while ((!isalphanum (*buf)) && strncmp (buf, example, strlen(example))) ;
  209. }
  210.  
  211.  
  212. do_man( void )
  213. {
  214.     FILE *f;
  215.     int i;
  216.     char buf[200], name[60], *src, *var, docfound=0;
  217.  
  218.     buf[0]=0;
  219.     if( var=get_var(LEVEL_SET,"_man" ) )
  220.         strcpy(buf,var);
  221.  
  222.     if (ac==1) ac=2, av[1]="MAN";
  223.     for (i=1; i<ac; i++) {
  224.         src=buf, helpfound=0;
  225.         while( exword( &src, name) )
  226.             if( f=fopen(name, "r") ) {
  227.                 docfound=1;
  228.                 man(f, av[i]);
  229.                 fclose(f);
  230.                 if( helpfound )
  231.                     break;
  232.             }
  233.         if( !docfound )
  234.             fprintf(stderr,"%s not found\n",buf);
  235.         else if( !helpfound )
  236.             fprintf(stderr, "Help not found for %s\n", av[i]);
  237.     }
  238.     return 0;
  239. }
  240.  
  241. do_assign( void )
  242. {
  243.     int i;
  244.  
  245.     if     (  ac==1  ) assignlist();
  246.     else if(  ac==2  ) doassign(av[1], NULL);
  247.     else if( !(ac&1) ) ierror(NULL, 500);
  248.     else
  249.         for( i=1; i<ac; i+=2 )
  250.             doassign( av[i],av[i+1] );
  251.     return 0;
  252. }
  253.  
  254. /* AMK: rewritten code, removed bug when strlen(log) was 0 */
  255. static void
  256. doassign(char *log, char *phy)
  257. {
  258.     int last=strlen(log);
  259.  
  260.     if (last<2 || log[last-1] != ':') fprintf(stderr, "Bad name %s\n", log);
  261.     else {
  262.         int succ=0;
  263.  
  264.         log[last-1] = 0;
  265.  
  266.         if (!phy)
  267.             succ=AssignLock(log,NULL);
  268.         else if (options&1) {   /* add assign, CLI: assign ADD */
  269.             BPTR lock;
  270.             if( lock=Lock(phy,ACCESS_READ) )
  271.                 if( !(succ=AssignAdd(log,lock)))
  272.                     UnLock(lock);
  273.         }
  274.  
  275.         /* late-binding assign, CLI: assign DEFER */
  276.         else if (options&2 || options&8)
  277.             succ=AssignLate(log,phy);
  278.  
  279.         /* non-binding assign, CLI: assign PATH */
  280.         else if (options&4 || options&16)
  281.             succ=AssignPath(log,phy);
  282.         else if (!options) {
  283.             BPTR lock;
  284.             if( lock=Lock(phy,ACCESS_READ) )
  285.                 if( !(succ=AssignLock(log,lock)))
  286.                     UnLock(lock);
  287.         }
  288.  
  289.         if( !succ )
  290.             pError( log );
  291.     }
  292. }
  293.  
  294.  
  295. static void
  296. assignlist()
  297. {
  298.     char *ptr;
  299.     struct DosList *dl;
  300.     struct AssignList *path;
  301.     ULONG flags;
  302.     char fmt[256],devname[256];
  303.     char **dev_list;
  304.     long dev_num,i,cnt;
  305.  
  306.     dev_list = NULL;
  307.     dev_num  = 0;
  308.     flags    = LDF_VOLUMES|LDF_READ;
  309.  
  310.     if (dl=LockDosList(flags)) {
  311.         while (dl=NextDosEntry(dl,flags)) {
  312.             BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  313.             sprintf(fmt,"%s%s",devname,
  314.                     dl->dol_misc.dol_volume.dol_LockList?"":" [Mounted]");
  315.             add_array_list(&dev_list,&dev_num,fmt);
  316.         }
  317.         UnLockDosList(flags);
  318.     }
  319.  
  320.     QuickSort(dev_list,dev_num);
  321.     printf("Volumes:\n");
  322.     for(i=0; i<dev_num; i++)
  323.         printf("%s\n",dev_list[i]);
  324.     free_array_list(dev_list,dev_num);
  325.  
  326.     if (dobreak())
  327.         return;
  328.  
  329.     dev_list = NULL;
  330.     dev_num  = 0;
  331.     flags    = LDF_ASSIGNS|LDF_READ;
  332.  
  333.     if (dl=LockDosList(flags)) {
  334.         while (dl=NextDosEntry(dl,flags)) {
  335.             BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  336.  
  337.             sprintf(fmt,"%-14s ",devname);
  338.             ptr = fmt+strlen(fmt);
  339.  
  340.             switch (dl->dol_Type) {
  341.                 case DLT_DIRECTORY :
  342.                     if(dl->dol_Lock) {
  343.                         if (!NameFromLock(dl->dol_Lock,ptr,200L)) {
  344.                             fprintf(stderr,"csh.assignlist.1: NameFromLock() failed\n");
  345.                             strcpy(ptr,"Lock's name too long");
  346.                         }
  347.                     }
  348.                     else
  349.                         strcpy(ptr,"Nonexisting lock");
  350. /* --- */
  351.                     if (path=dl->dol_misc.dol_assign.dol_List) {
  352.                         char **ass_list=NULL;
  353.                         long ass_num=0,str_len=0;
  354.                         char *ass_str;
  355.  
  356.                         add_array_list(&ass_list,&ass_num,fmt);
  357.                         str_len += strlen(fmt);
  358.  
  359.                         for (; path; path=path->al_Next) {
  360.                             sprintf(fmt,"%-13s+ ","");
  361.                             ptr = fmt+strlen(fmt);
  362.                             if (dl->dol_Lock) {
  363.                                 if (!NameFromLock(path->al_Lock,ptr,200L)) {
  364.                                     fprintf(stderr,"csh.assignlist.2: NameFromLock() failed\n");
  365.                                     strcpy(ptr,"Lock's name too long");
  366.                                 }
  367.                             }
  368.                             else
  369.                                 strcpy(ptr,"Nonexisting lock");
  370.                             add_array_list(&ass_list,&ass_num,fmt);
  371.                             str_len += strlen(fmt)+1;
  372.                         }
  373.  
  374.                         if (ass_str=malloc(str_len+1)) {
  375.                             char *p=ass_str;
  376.                             for(i=0; i<ass_num; i++) {
  377.                                 strcpy(p,ass_list[i]);
  378.                                 p += strlen(p);
  379.                                 if ((i+1)<ass_num) {
  380.                                     *p++ = '\n';
  381.                                     *p   = '\0';
  382.                                 }
  383.                             }
  384.                             add_array_list(&dev_list,&dev_num,ass_str);
  385.                             free(ass_str);
  386.                         }
  387.  
  388.                         free_array_list(ass_list,ass_num);
  389.                     }
  390.                     else
  391.                         add_array_list(&dev_list,&dev_num,fmt);
  392. /* --- */
  393. #if 0
  394.                     add_array_list(&dev_list,&dev_num,fmt);
  395.  
  396.                     for(path=dl->dol_misc.dol_assign.dol_List; path; path=path->al_Next) {
  397.                         sprintf(fmt,"%-13s+ ","");
  398.                         ptr = fmt+strlen(fmt);
  399.                         if (dl->dol_Lock) {
  400.                             if (!NameFromLock(path->al_Lock,ptr,200L)) {
  401.                                 fprintf(stderr,"csh.assignlist.3: NameFromLock() failed\n");
  402.                                 strcpy(ptr,"Lock's name too long");
  403.                             }
  404.                         }
  405.                         else
  406.                             strcpy(ptr,"Nonexisting lock");
  407.                         add_array_list(&dev_list,&dev_num,fmt);
  408.                     }
  409. #endif
  410.                     break;
  411.                 case DLT_LATE      :
  412.                     sprintf(ptr,"<%s>",dl->dol_misc.dol_assign.dol_AssignName);
  413.                     add_array_list(&dev_list,&dev_num,fmt);
  414.                     break;
  415.                 case DLT_NONBINDING:
  416.                     sprintf(ptr,"[%s]",dl->dol_misc.dol_assign.dol_AssignName);
  417.                     add_array_list(&dev_list,&dev_num,fmt);
  418.                     break;
  419.                 default:
  420.                     strcpy(ptr,"Unknown assign");
  421.                     add_array_list(&dev_list,&dev_num,fmt);
  422.                     break;
  423.             }
  424.         }
  425.         UnLockDosList(flags);
  426.     }
  427.  
  428.     QuickSort(dev_list,dev_num);
  429.     printf("\nDirectories:\n");
  430.     for(i=0; !dobreak() && i<dev_num; i++)
  431.         printf("%s\n",dev_list[i]);
  432.     free_array_list(dev_list,dev_num);
  433.  
  434.     if (dobreak())
  435.         return;
  436.  
  437.     dev_list = NULL;
  438.     dev_num  = 0;
  439.     flags    = LDF_DEVICES|LDF_READ;
  440.  
  441.     if (dl=LockDosList(flags)) {
  442.         while (dl=NextDosEntry(dl,flags)) {
  443.             if (dl->dol_Task) {
  444.                 BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  445.                 add_array_list(&dev_list,&dev_num,devname);
  446.             }
  447.         }
  448.         UnLockDosList(flags);
  449.     }
  450.  
  451.     QuickSort(dev_list,dev_num);
  452.     printf("\nDevices (with FileSystem):\n");
  453.     for(i=0,cnt=0; i<dev_num; i++) {
  454.         if (IsFileSystem(dev_list[i])) {
  455.             if (cnt>0 && cnt%5==0)
  456.                 printf("\n");
  457.             printf("%s ",dev_list[i]);
  458.             ++cnt;
  459.         }
  460.     }
  461.     printf("\n");
  462.     free_array_list(dev_list,dev_num);
  463.  
  464.     if (dobreak())
  465.         return;
  466.  
  467.     dev_list = NULL;
  468.     dev_num  = 0;
  469.     flags    = LDF_DEVICES|LDF_READ;
  470.  
  471.     if (dl=LockDosList(flags)) {
  472.         while (dl=NextDosEntry(dl,flags)) {
  473.             BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  474.             add_array_list(&dev_list,&dev_num,devname);
  475.         }
  476.         UnLockDosList(flags);
  477.     }
  478.  
  479.     QuickSort(dev_list,dev_num);
  480.     printf("\nDevices:\n");
  481.     for(i=0; i<dev_num; i++) {
  482.         if (i>0 && i%5==0)
  483.             printf("\n");
  484.         printf("%s ",dev_list[i]);
  485.     }
  486.     printf("\n");
  487.     free_array_list(dev_list,dev_num);
  488.  
  489. return;
  490. #if 0
  491.     printf("\nDirectories:\n");
  492.     for( ; arr[i] && !dobreak(); i++ ) {
  493.         log=arr[i]+1; ptr=log+strlen(log)+1;
  494.         switch( *(log-1)) {
  495.         case 3:
  496.             printf("%-20s%s\n", log, ptr);
  497.             for(;;) {
  498.                 ptr+=strlen(ptr)+1;
  499.                 if( !*ptr ) break;
  500.                     printf("%-19s+%s\n", "", ptr);
  501.             }
  502.             break;
  503.         case 4: printf("%-20s<%s>\n", log, ptr); break;
  504.         case 5: printf("%-20s[%s]\n", log, ptr); break;
  505.         }
  506.     }
  507. #endif
  508. }
  509.  
  510.  
  511.  
  512. do_join( void )
  513. {
  514.     BPTR sou, dest;
  515.     char *buffer;
  516.     int i;
  517.     long n;
  518.     char *namedest=av[--ac];
  519.  
  520.     if (options==0 && exists(namedest)) { ierror(namedest,203); return 20; }
  521.     if ( (buffer=malloc(8192)) == NULL ) { ierror(NULL,103); return 20; }
  522.     if ( (dest=Open(namedest, MODE_NEWFILE)) == NULL )
  523.         { pError(namedest); goto fail1; }
  524.     for (i=1; i<ac; i++) {
  525.         if ( (sou=Open(av[i], MODE_OLDFILE)) == NULL ) pError(av[i]);
  526.         else
  527.             while( (n=Read(sou, buffer, 8192L)) > 0 )
  528.                 if (Write(dest, buffer, n) != n)
  529.                     { pError(namedest); Close(sou); goto fail2; }
  530.         Close(sou);
  531.     }
  532. fail2:
  533.     Close(dest);
  534. fail1:
  535.     free(buffer);
  536.     return 0;
  537. }
  538.  
  539. #define BUFDIM 512L
  540. #define MAXSTR 256
  541.  
  542. int minstr;
  543.  
  544. static int
  545. strings_in_file(long mask, char *s, char *path)
  546. {
  547.     long n,i;
  548.     char c;
  549.     char readbuf[BUFDIM+1], strbuf[MAXSTR+1];
  550.     BPTR fh;
  551.     int strctr=0;
  552.     BOOL out, hdout = TRUE;  /* hdout = header output */
  553.     BOOL usestdin = (s==NULL);
  554.     BOOL inter = IsInteractive(Output());
  555.  
  556.     prepscroll(0);
  557.  
  558.     if (usestdin)
  559.         fh = Input();
  560.     else
  561.         fh = Open(s,MODE_OLDFILE);
  562.  
  563.     if (fh) {
  564.         while ( (n=Read(fh, readbuf, BUFDIM))>0 && !CHECKBREAK() )
  565.             for (i=0; i<n && !CHECKBREAK(); i++) {   /* GMD: speed up ^C reaction */
  566.                 c=readbuf[i];
  567.                 if (c<0x20 || c>0x7f) {
  568.                     out=(strctr>=minstr);
  569.                     if (!out) strctr=0;
  570.                 } else {
  571.                     strbuf[strctr++]=c;
  572.                     out=(strctr>=BUFDIM);
  573.                 }
  574.                 if (out) {
  575.                     strbuf[strctr]='\0';
  576.                     if (options&8 && hdout) {
  577.                             printf("Strings in %s (len>=%d):\n",path?path:"STDIN",minstr);
  578.                             hdout=FALSE;
  579.                     }
  580.                     printf("%s%s%s%s%s\n",
  581.                         (options&4) ? (path?path:"STDIN") : "",
  582.                         (options&4) ? ": " : "",
  583.                         (options&2) ? "|" : "",
  584.                         strbuf,
  585.                         (options&2) ? "|" : "");
  586. #if 0
  587.                     if (options&2) {
  588.                         printf("%s: |%s|\n",path?path:"STDIN",strbuf);
  589.                     }
  590.                     else {
  591.                         if (hdout) {
  592.                             printf("Strings in %s (len>=%d):\n",path?path:"STDIN",minstr);
  593.                             hdout=FALSE;
  594.                         }
  595.                         puts(strbuf);
  596.                     }
  597. #endif
  598.                     if (inter) fflush(stdout);
  599.                     quickscroll();
  600.                     strctr=0;
  601.                 }
  602.             }
  603.         /* only close file if not standard input */
  604.         if (!usestdin)
  605.             Close(fh);
  606.     } else
  607.         pError(s);
  608.  
  609.     return 0;
  610. }
  611.  
  612. do_strings( void )
  613. {
  614.     if (isnum(av[ac-1])) {
  615.         minstr = myatoi(av[--ac],1,255);
  616.         if (atoierr) {
  617.             fprintf(stderr,"Need a valid string length parameter (1-255)!\n");
  618.             return 0;
  619.         }
  620.     }
  621.     else
  622.         minstr = 4;
  623.  
  624.     if (ac<2)
  625.         strings_in_file(0, NULL, NULL);
  626.     else
  627.         all_args( strings_in_file, 0);
  628.  
  629.     return 0;
  630. }
  631.  
  632. BPTR myfile[MAXMYFILES];
  633.  
  634. do_open( void )
  635. {
  636.     long mode;
  637.     int n;
  638.  
  639.     switch (toupper(av[2][0])) {
  640.         case 'R': mode=MODE_OLDFILE; break;
  641.         case 'W': mode=MODE_NEWFILE; break;
  642.         default : ierror(NULL,500); return 1;
  643.     }
  644.     n=myatoi(av[3],0,MAXMYFILES-1); if (atoierr) return 20;
  645.     if (myfile[n]) myclose(n);
  646.     myfile[n]=Open(av[1],mode);
  647.     return myfile[n]==NULL;
  648. }
  649.  
  650. do_close( void )
  651. {
  652.     int i, n;
  653.  
  654.     if (ac==1)
  655.         for (i=1; i<MAXMYFILES; i++)
  656.             myclose(i);
  657.     for (i=1; i<ac; i++) {
  658.         n=myatoi(av[i],0,MAXMYFILES-1); if (atoierr) return 20;
  659.         myclose(n);
  660.     }
  661.     return 0;
  662. }
  663.  
  664. void
  665. myclose(int n)
  666. {
  667.     if (myfile[n]) { Close(myfile[n]); myfile[n]=NULL; }
  668. }
  669.  
  670. do_fileslist( void )
  671. {
  672.     int i, flag=0;
  673.  
  674.     printf("Open files:");
  675.     for (i=0; i<MAXMYFILES; i++)
  676.         if (myfile[i]) { printf(" %d",i); flag=1; }
  677.     if (!flag) printf(" None!");
  678.     printf("\n");
  679.     return 0;
  680. }
  681.  
  682. BPTR
  683. extOpen( char *name, long mode )
  684. {
  685.     if (name[0]=='.' && name[1]>='0' && name[1]<='9')
  686.         return myfile[atoi(name+1)];
  687.     return Open(name,mode);
  688. }
  689.  
  690.  
  691. void
  692. extClose(BPTR fh)
  693. {
  694.     int i;
  695.  
  696.     for (i=0; i<MAXMYFILES; i++)
  697.         if (myfile[i]==fh) return;
  698.     Close(fh);
  699. }
  700.  
  701. do_basename( void )
  702. {
  703.     char *res;
  704.     int  i;
  705.  
  706.     for( i=2; i<ac; i++ )
  707.         av[i]=FilePart(av[i]);
  708.     set_var(LEVEL_SET, av[1], res=compile_av(av,2,ac,0xA0,0));
  709.     free(res);
  710.     return 0;
  711. }
  712.  
  713. do_tackon( void )
  714. {
  715.     char buf[256];
  716.  
  717.     strcpy(buf, av[2]);
  718.     AddPart(buf, av[3], 256L);
  719.     set_var(LEVEL_SET, av[1], buf);
  720.     return 0;
  721. }
  722.  
  723. extern char shellres[];
  724.  
  725. do_resident( void )
  726. {
  727.     struct Segment *seg;
  728.     char buf[256],devname[256];
  729.     char **dev_list1=NULL,**dev_list2=NULL;
  730.     long dev_num1=0,dev_num2=0,i;
  731.  
  732.     if (options==0 && ac>1) options=1;
  733.     switch (options) {
  734.     case 0:
  735.         Forbid();
  736.         seg = (struct Segment *)BADDR(((struct DosInfo *)BADDR(DOSBase->dl_Root->rn_Info))->di_NetHand);
  737.         while (seg) {
  738.             BtoCStr(devname,MKBADDR(seg->seg_Name),254L);  /* 256 - '\0' + ':' */
  739.             if (seg->seg_UC >= 0) {
  740.                 sprintf(buf,"%-18s%4.1ld",devname,seg->seg_UC-1);
  741.                 add_array_list(&dev_list1,&dev_num1,buf);
  742.             }
  743.             else {
  744.                 switch (seg->seg_UC) {
  745.                 case CMD_INTERNAL:
  746.                     sprintf(buf,"%-18s%s",devname,"INTERNAL");
  747.                     add_array_list(&dev_list2,&dev_num2,buf);
  748.                     break;
  749.                 case CMD_SYSTEM:
  750. /* don't print this */ /*
  751.                     sprintf(buf,"%-18s%s",devname,"SYSTEM");
  752.                     add_array_list(&dev_list2,&dev_num2,buf);
  753. */
  754.                     break;
  755.                 case CMD_DISABLED:
  756.                     sprintf(buf,"%-18s%s",devname,"DISABLED");
  757.                     add_array_list(&dev_list2,&dev_num2,buf);
  758.                     break;
  759.                 default:
  760.                     sprintf(buf,"%-18s%s",devname,"UNKNOWN");
  761.                     add_array_list(&dev_list2,&dev_num2,buf);
  762.                     break;
  763.                 }
  764.             }
  765.             seg = (struct Segment *)BADDR(seg->seg_Next);
  766.         }
  767.         Permit();
  768.         printf("NAME              USE COUNT\n\n");
  769.  
  770.         QuickSort(dev_list1,dev_num1);
  771.         for(i=0; !dobreak() && i<dev_num1; i++)
  772.             printf("%s\n",dev_list1[i]);
  773.         free_array_list(dev_list1,dev_num1);
  774.  
  775.         for(i=0; !dobreak() && i<dev_num2; i++)
  776.             printf("%s\n",dev_list2[i]);
  777.         free_array_list(dev_list2,dev_num2);
  778.  
  779.         break;
  780.     case 1:
  781.         for (i=1; i<ac; i++)
  782.             if (loadres(av[i]))
  783.                 printf("OK! %s is now resident\n", FilePart(av[i]));
  784.             else
  785.                 pError(av[i]);
  786.         break;
  787.     case 2:
  788.         for (i=1; i<ac; i++) {
  789.             Forbid();
  790.             if (seg=FindSegment(av[i],NULL,0L)) {
  791.                 if (RemSegment(seg)) {
  792.                     Permit();
  793.                     printf("Removed %s\n",av[i]);
  794.                 }
  795.                 else {
  796.                     Permit();
  797.                     ierror(av[i],ERROR_OBJECT_IN_USE);
  798.                 }
  799.             }
  800.             else {
  801.                 Permit();
  802.                 ierror(av[i],ERROR_OBJECT_NOT_FOUND);
  803.             }
  804.         }
  805.         break;
  806.     case 4:
  807.         for (i=1; i<ac; i++) {
  808.             if( !o_resident ) {
  809.                 /* AMK: OS20-SetVar replaces ARP-Setenv */
  810.                 SetVar(shellres,"1",-1L,GVF_GLOBAL_ONLY|GVF_BINARY_VAR);
  811.                 o_resident=1;
  812.             }
  813.             sprintf(buf,"res_%s",FilePart(av[i]));
  814.             /* AMK: OS20-SetVar replaces ARP-Setenv */
  815.             SetVar(buf,av[i],-1L,GVF_GLOBAL_ONLY|GVF_BINARY_VAR);
  816.         }
  817.         break;
  818.     default:
  819.         ierror(NULL,500);
  820.         break;
  821.     }
  822.     return 0;
  823. }
  824.  
  825. int
  826. loadres(char *s)
  827. {
  828.     BPTR seg;
  829.     BOOL okay = FALSE;
  830.  
  831.     if (seg=NewLoadSeg(s,NULL))
  832.         okay=AddSegment(FilePart(s),seg,1L);
  833.  
  834.     return (okay);
  835. }
  836.  
  837. extern BPTR redir_out, redir_in;
  838.  
  839. struct TagItem tags[]={
  840.     {SYS_Input,  0},
  841.     {SYS_Output, 0},
  842.     {SYS_Asynch, 1},
  843.     {TAG_DONE,   0} };
  844.  
  845. do_truerun(char *avline, int backflag)
  846. {
  847.     BPTR input, output;
  848.     char *args;
  849.     int err;
  850.  
  851.     if (backflag) {
  852.         input = Open("NIL:",MODE_NEWFILE);
  853.         output= Open("NIL:",MODE_NEWFILE);
  854.     } else {
  855.         input = redir_in ?redir_in : Open("NIL:"    , MODE_NEWFILE);
  856.         output= redir_out?redir_out: Open("CONSOLE:", MODE_NEWFILE);
  857.     }
  858.  
  859.     args=compile_av(av,1,ac,' ',1);
  860.  
  861.     tags[0].ti_Data= input;
  862.     tags[1].ti_Data= output;
  863.  
  864.     err=System( args, tags );
  865.  
  866.     if( err!=0 ) {
  867.         Close( tags[0].ti_Data );
  868.         Close( tags[1].ti_Data );
  869.         pError(av[1]);
  870.     }
  871.     free(args);
  872.  
  873.     return 0;
  874. }
  875.  
  876. #if 0
  877. extern BPTR redir_out, redir_in;
  878.  
  879. static struct ProcessControlBlock pcb={
  880.     4000,        /* pcb_StackSize    */
  881.     0,        /* pcb_Pri        */
  882.     };
  883. /* remaining fields are NULL */
  884.  
  885. do_truerun(char *avline, int backflag)
  886. {
  887.     char name[100], *args, buf[10];
  888.     int cli;
  889.  
  890.     args=next_word(next_word(avline));
  891.     if (backflag) {
  892.         pcb.pcb_Control= 0;
  893.         pcb.pcb_Input  = Open("NIL:",MODE_OLDFILE);
  894.         pcb.pcb_Output = Open("NIL:",MODE_OLDFILE);
  895.     } else {
  896.         pcb.pcb_Control= 0;
  897.         pcb.pcb_Input  = redir_in;
  898.         pcb.pcb_Output = redir_out;
  899.  
  900.     }
  901.  
  902.     if((cli=ASyncRun(av[1],args,&pcb))<0)
  903.         if (dofind(av[1], "", name,v_path))
  904.             cli=ASyncRun(name,args,&pcb);
  905.  
  906.     if( cli<0 && cli>=-11 ) {
  907.         if( redir_out ) extClose( redir_out );
  908.         if( redir_in  ) extClose( redir_in  );
  909.     }
  910.  
  911.     sprintf(buf,"%d",cli);
  912.     set_var(LEVEL_SET,"_newproc",buf);
  913.  
  914.     if( cli<0 ) {
  915.         ierror(av[1],205);
  916.         return 20;
  917.     }
  918.     return 0;
  919. }
  920. #endif
  921.  
  922. int
  923. exists( char *name )
  924. {
  925.     BPTR lock;
  926.     char *nam=FilePart(name);
  927.     int ret=0;
  928.  
  929.     Myprocess->pr_WindowPtr = (APTR)(-1);
  930.     if ( strlen(nam)<=MAXFILENAME && (lock=Lock(name,ACCESS_READ))) {
  931.         UnLock(lock);
  932.         ret=1;
  933.     }
  934.     Myprocess->pr_WindowPtr = o_noreq ? (APTR) -1L : Mywindow;
  935.     return ret;
  936. }
  937.  
  938. int
  939. mounted( char *dev )
  940. {
  941.     struct DosList *dl;
  942.     ULONG flags = LDF_ALL|LDF_READ;
  943.     int gotcha = FALSE;
  944.     char devname[256];
  945.  
  946.     if (dl=LockDosList(flags)) {
  947.         while ((!gotcha) && (dl=NextDosEntry(dl,flags))) {
  948.             BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  949.             if (stricmp(devname,dev)==0)
  950.                 gotcha = TRUE;
  951.         }
  952.         UnLockDosList(flags);
  953.     }
  954.  
  955.     return (gotcha);
  956. }
  957.  
  958. #define HTYPELINE 16L
  959.  
  960. static int
  961. htype_a_file(long mask, char *s, char *path)
  962. {
  963.     BPTR fh;
  964.     long n, filesize=0;
  965.     UBYTE buf[HTYPELINE+1];
  966.     char out[80], *put;
  967.     int i, inter=IsInteractive(Output());
  968.     BOOL usestdin = (s==NULL);
  969.  
  970.     if (usestdin)
  971.         fh = Input();
  972.     else
  973.         fh = Open(s,MODE_OLDFILE);
  974.  
  975.     if (fh==NULL) { pError(s); return 20; }
  976.     prepscroll(0);
  977.     while ( (n=Read(fh,(char *)buf,HTYPELINE))>0 && !dobreak()) {
  978.         put=out;
  979.         put+=sprintf(put,"%06lx: ",filesize);
  980.         filesize+=n;
  981.         for (i=0; i<n; i++) {
  982.             put+=sprintf( put,(i&3) ? "%02x" : " %02x",buf[i]);
  983.             if ((buf[i]&127)<0x20) buf[i]='.';
  984.         }
  985.         for ( ; i<HTYPELINE; i++) {
  986.             put+=sprintf( put, (i&3) ? "  " : "   ");
  987.             buf[i]=' ';
  988.         }
  989.         buf[i]=0;
  990.         sprintf(put,"    %s",buf);
  991.         puts(out);
  992.         if( inter ) fflush(stdout);
  993.         quickscroll();
  994.     }
  995.     /* only close file if not standard input */
  996.     if (!usestdin)
  997.         Close(fh);
  998.     return 0;
  999. }
  1000.  
  1001. do_htype( void )
  1002. {
  1003.     if (ac<2)
  1004.         htype_a_file(0, NULL, NULL);
  1005.     else
  1006.         all_args( htype_a_file, 0);
  1007.     return 0;
  1008. }
  1009.  
  1010. #define STACK_MIN_FREE 10000
  1011. do_stack( void )
  1012. {
  1013.     long n;
  1014.  
  1015.     if (ac>1) {
  1016.         if (isnum(av[1])) {   /* AMK: IoErr() replaced by isnum() */
  1017.             n=atol(av[1]);
  1018.             if ( n < 1600 )
  1019.                 printf("Requested size too small\n");
  1020.             else if ( n > (AvailMem(MEMF_LARGEST)-STACK_MIN_FREE) )
  1021.                 printf("Requested size too large\n");
  1022.             else
  1023.             Mycli->cli_DefaultStack=(long)(n >> 2L);
  1024.         }
  1025.         else {
  1026.             ierror(av[1],511);   /* AMK: message if error */
  1027.             return 20;
  1028.         }
  1029.     }
  1030.     else {
  1031.         if (options&1)
  1032.             printf("%ld\n",(long)Mycli->cli_DefaultStack << 2L);
  1033.         else
  1034.             printf("current stack size is %ld bytes\n",
  1035.                     (long)Mycli->cli_DefaultStack << 2L);
  1036.     }
  1037.     return 0;
  1038. }
  1039.  
  1040. do_fault( void )
  1041. {
  1042.     PERROR *p;
  1043.     int i, n;
  1044.  
  1045.     for (i=1; i<ac; i++) {
  1046.         n=myatoi(av[i],0,32767);
  1047.         if (!atoierr) {
  1048.             for (p=Perror; p->errnum && p->errnum!=n; p++);
  1049.             if (p->errnum)
  1050.                 printf("Fault %d: %s\n",n,p->errstr);
  1051.             else
  1052.                 printf("Fault %d not recognized\n",n);
  1053.         }
  1054.     }
  1055.     return 0;
  1056. }
  1057.  
  1058. struct rpncommand {
  1059.     char *str;
  1060.     int parsin, parsout;
  1061.     };
  1062.  
  1063. static struct rpncommand rpn[]={
  1064.     "+",    2,    1,
  1065.     "-",    2,    1,
  1066.     "*",    2,    1,
  1067.     "/",    2,    1,
  1068.     "%",    2,    1,
  1069.     "&",    2,    1,
  1070.     "|",    2,    1,
  1071.     "~",    1,    1,
  1072.     ">",    2,    1,
  1073.     "<",    2,    1,
  1074.     "==",    2,    1,
  1075.     "!",    1,    1,
  1076.     "MAX",    2,    1,
  1077.     "MIN",    2,    1,
  1078.     "DUP",    1,    2,
  1079.     "DROP",    1,    0,
  1080.     "SWAP",    2,    2,
  1081.     "HELP",    0,    0,
  1082.     NULL,    0,    1,    /* this looks for a number */
  1083. };
  1084.  
  1085. static long stack[50];
  1086. static int sp;
  1087.  
  1088.  
  1089. eval_rpn( char **av, int ac, int flag )
  1090. {
  1091.     char *zero="Division by zero\n";
  1092.     struct rpncommand *temp;
  1093.     long n0, n1, t;
  1094.     int j, i=0, oldsp=sp;
  1095.  
  1096.     for (; i<ac; i++) {
  1097.         for (j=0; rpn[j].str && stricmp(rpn[j].str,av[i]); j++) ;
  1098.         n0=stack[sp-1];
  1099.         n1=stack[sp-2];
  1100.         sp -= (rpn[j].parsin);
  1101.         if (sp<0) { fprintf(stderr, "RPN: Empty stack\n"); goto error; }
  1102.         switch (j) {
  1103.           case 0:    n0 += n1;            break;
  1104.           case 1:    n0 = n1-n0;            break;
  1105.           case 2:    n0 *= n1;            break;
  1106.           case 3:    if(n0) n0=n1/n0; else fprintf(stderr,zero); break;
  1107.           case 4:    if(n0) n0=n1%n0; else fprintf(stderr,zero); break;
  1108.           case 5:    n0 &= n1;            break;
  1109.           case 6:    n0 |= n1;            break;
  1110.           case 7:    n0 =  ~n0    ;        break;
  1111.           case 8:    n0 = (n1 > n0);        break;
  1112.           case 9:    n0 = (n1 < n0);        break;
  1113.           case 10:    n0 = (n0 == n1);    break;
  1114.           case 11:    n0 = !n0;            break;
  1115.           case 12:    n0=n1>n0 ? n1 : n0;    break;
  1116.           case 13:    n0=n1<n0 ? n1 : n0;    break;
  1117.           case 14:    n1=n0;                break;
  1118.           case 15:    t=n0; n0=n1; n1=t;    break;
  1119.           case 16:                        break;
  1120.           case 17:    printf("In Commands Out\n");
  1121.             for (temp=rpn; temp->str; temp++)
  1122.                 printf(" %d %-10s%d\n",
  1123.                 temp->parsin,temp->str,temp->parsout);
  1124.             break;
  1125.           default:    n0=atol(av[i]);
  1126.                 if (!isnum(av[i])) {   /* AMK: IoErr() replaced by isnum() */
  1127.                     fprintf(stderr, "Bad RPN cmd: %s\n",av[i]);
  1128.                     goto error;
  1129.                 }
  1130.                 break;
  1131.           }
  1132.         stack[sp]=n0;
  1133.         stack[sp+1]=n1;
  1134.         sp += rpn[j].parsout;
  1135.     }
  1136.     if( flag && sp-1)
  1137.         fprintf( 
  1138.           stderr,
  1139.           "RPN: Stack not empty\n"
  1140.         );
  1141.  
  1142.     t=sp; sp=oldsp;
  1143.     if( flag )
  1144.         return stack[t-1]; /* return top value */
  1145.     else
  1146.         return t-sp;
  1147.  
  1148. error:
  1149.     sp=oldsp;
  1150.     return 0;
  1151. }
  1152.  
  1153.  
  1154. do_rpn(char *garbage,int ifflag) /* ifflag!=0 if called from if */
  1155. {
  1156.     int i=1;
  1157.     long t;
  1158.  
  1159.     t=eval_rpn( av+i, ac-i, ifflag );
  1160.     if (ifflag) return t;              /* called from if: return top value */
  1161.     for (i=sp+t-1;i>=sp;i--) printf("%ld\n", stack[i]);/* else print stack */
  1162.  
  1163.     return t ? 0 : 20;
  1164. }
  1165.  
  1166.  
  1167.  
  1168. void *DosAllocMem(long size)
  1169. {
  1170.     return( AllocVec(size,MEMF_CLEAR|MEMF_PUBLIC) );
  1171. }
  1172.  
  1173.  
  1174.  
  1175. void DosFreeMem(void *block)
  1176. {
  1177.     FreeVec(block);
  1178. }
  1179.  
  1180.  
  1181.  
  1182. /* do_rehash related stuff ... */
  1183.  
  1184. #define PATHHASH_RSRC "CSH-PathHash"
  1185. #define PATHHASH_SEMA "CSH-PathHash"
  1186.  
  1187. struct PathHashRsrc {
  1188.     struct Library phr_Lib;
  1189.     struct SignalSemaphore phr_Sema;
  1190.     long phr_entries;
  1191.     char *phr_data;
  1192. };
  1193.  
  1194.  
  1195.  
  1196. char *get_rehash_prog(char *last,char *progname)
  1197. {
  1198.     long i;
  1199.     char *filepart;
  1200.  
  1201.     if (last) {
  1202.         for(i=0; i<prghash_num && prghash_list[i]!=last; i++)
  1203.             ;
  1204.  
  1205.         for(++i; i<prghash_num; i++) {
  1206.             if (filepart=FilePart(prghash_list[i])) {
  1207.                 if (strnicmp(progname,filepart,strlen(progname))==0)
  1208.                     return( prghash_list[i] );
  1209.             }
  1210.         }
  1211.     }
  1212.  
  1213.     for(i=0; i<prghash_num; i++) {
  1214.         if (filepart=FilePart(prghash_list[i])) {
  1215.             if (strnicmp(progname,filepart,strlen(progname))==0)
  1216.                 return( prghash_list[i] );
  1217.         }
  1218.     }
  1219.  
  1220.     return( NULL );
  1221. }
  1222.  
  1223.  
  1224.  
  1225. void resolve_multiassign(char *ma,char ***dev_list,long *dev_num)
  1226. {
  1227.     struct DosList *dl;
  1228.     struct AssignList *path;
  1229.     ULONG flags;
  1230.     char *colon;
  1231.     char fmt[256],devname[256];
  1232.  
  1233.     flags = LDF_ASSIGNS|LDF_READ;
  1234.     colon = strchr(ma,':');
  1235.  
  1236.     if (colon && (dl=LockDosList(flags))) {
  1237.         *colon = '\0';
  1238.         while (dl=NextDosEntry(dl,flags)) {
  1239.             BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  1240.  
  1241.             if (stricmp(devname,ma)==0) {
  1242.  
  1243.                 if (dl->dol_Type == DLT_DIRECTORY) {
  1244.                     if(dl->dol_Lock) {
  1245.                         if (NameFromLock(dl->dol_Lock,fmt,255L)) {
  1246.                             if (*(colon+1))
  1247.                                 AddPart(fmt,colon+1,255);
  1248.                             add_array_list(dev_list,dev_num,fmt);
  1249.                         }
  1250.                         else {
  1251.                             fprintf(stderr,"csh.resolve_multiassign.1: NameFromLock() failed\n");
  1252.                         }
  1253.                     }
  1254.                     else
  1255.                         printf("Nonexisting lock (1) %s\n",devname);
  1256.  
  1257.                     if (path=dl->dol_misc.dol_assign.dol_List) {
  1258.                         for (; path; path=path->al_Next) {
  1259.                             if (dl->dol_Lock) {
  1260.                                 if (NameFromLock(path->al_Lock,fmt,255L)) {
  1261.                                     if (*(colon+1))
  1262.                                         AddPart(fmt,colon+1,255);
  1263.                                     add_array_list(dev_list,dev_num,fmt);
  1264.                                 }
  1265.                                 else {
  1266.                                     fprintf(stderr,"csh.resolve_multiassign.2: NameFromLock() failed\n");
  1267.                                 }
  1268.                             }
  1269.                             else
  1270.                                 printf("Nonexisting lock (2) %s\n",devname);
  1271.                         }
  1272.                     }
  1273.                 }
  1274.             }
  1275.         }
  1276.         UnLockDosList(flags);
  1277.         *colon = ':';
  1278.     }
  1279. }
  1280.  
  1281.  
  1282.  
  1283. void remove_local_pathhash(void)
  1284. {
  1285.     free_array_list(prghash_list,prghash_num);
  1286.     prghash_list = NULL;
  1287.     prghash_num  = 0;
  1288. }
  1289.  
  1290.  
  1291.  
  1292. BOOL remove_global_pathhash(void)
  1293. {
  1294.     struct PathHashRsrc *rsrc;
  1295.     BOOL success = FALSE;
  1296.  
  1297.     Forbid();
  1298.     if (rsrc = OpenResource(PATHHASH_RSRC)) {
  1299.         if (rsrc->phr_Lib.lib_OpenCnt == 0) {
  1300.             RemResource(rsrc);
  1301.             RemSemaphore(&rsrc->phr_Sema);
  1302.             FreeVec(rsrc->phr_Sema.ss_Link.ln_Name);
  1303.             FreeVec(rsrc->phr_Lib.lib_Node.ln_Name);
  1304.             if (rsrc->phr_data) FreeVec(rsrc->phr_data);
  1305.             FreeVec(rsrc);
  1306.             success = TRUE;
  1307.         }
  1308.     }
  1309.     Permit();
  1310.  
  1311.     return(success);
  1312. }
  1313.  
  1314.  
  1315.  
  1316. void load_pathhash_from_mem(struct PathHashRsrc *rsrc)
  1317. {
  1318.     char *cp;
  1319.     long i;
  1320.  
  1321.     remove_local_pathhash();
  1322.  
  1323.     cp = rsrc->phr_data;
  1324.  
  1325.     for (i=rsrc->phr_entries; i>0; i--) {
  1326.         add_array_list(&prghash_list,&prghash_num,cp);
  1327.         cp += strlen(cp)+1;
  1328.     }
  1329. }
  1330.  
  1331.  
  1332.  
  1333. void save_pathhash_to_mem(struct PathHashRsrc *rsrc,long hashlen)
  1334. {
  1335.     char *new_data;
  1336.  
  1337.     if (new_data = AllocVec(hashlen,MEMF_PUBLIC|MEMF_CLEAR)) {
  1338.         long slen,i;
  1339.  
  1340.         /* free old path hash data */
  1341.         if (rsrc->phr_data) FreeVec(rsrc->phr_data);
  1342.  
  1343.         /* set new memory pointer */
  1344.         rsrc->phr_data = new_data;
  1345.  
  1346.         /* copy path hash data to memory */
  1347.         for(i=0; i<prghash_num; i++) {
  1348.             slen = strlen(prghash_list[i])+1;
  1349.             CopyMem(prghash_list[i],new_data,slen);
  1350.             new_data += slen;
  1351.         }
  1352.  
  1353.         /* set new number of entries */
  1354.         rsrc->phr_entries = prghash_num;
  1355.     }
  1356. }
  1357.  
  1358.  
  1359.  
  1360. do_rehash( void )
  1361. {
  1362.     /*
  1363.             (re-)build internal hash-list        (no option)
  1364.        -c : clear hash-list from memory          (options&1)
  1365.        -l : load hash-list from disk to memory   (options&2)
  1366.        -o : output hash-list from memory         (options&4)
  1367.        -s : save hash-list from memory to disk   (options&8)
  1368.        -g : free global hash-list                (options&16)
  1369.     */
  1370.     struct PathHashRsrc *rsrc;
  1371.     long i;
  1372.     char buf[256];
  1373.  
  1374.     if (options&1) {    /* clear hash-list */
  1375.  
  1376.         remove_local_pathhash();
  1377.     }
  1378.     else if (options&2) {    /* load hash-list */
  1379.         FILE *fp;
  1380.         char *lf,*fname;
  1381.         BOOL readin = FALSE;
  1382.  
  1383.         if (!(fname=get_var(LEVEL_SET,v_prghash))) {
  1384.             fprintf(stderr,"$_prghash unset\n");
  1385.             return 20;
  1386.         }
  1387.  
  1388.         Forbid();
  1389.         if (!(rsrc = OpenResource(PATHHASH_RSRC))) {
  1390.             if (rsrc=AllocVec(sizeof(struct PathHashRsrc),MEMF_PUBLIC|MEMF_CLEAR)) {
  1391.                 rsrc->phr_Lib.lib_Node.ln_Type = NT_RESOURCE;
  1392.                 rsrc->phr_Lib.lib_Node.ln_Pri  = 0;
  1393.                 if (rsrc->phr_Lib.lib_Node.ln_Name=AllocVec(strlen(PATHHASH_RSRC)+1,MEMF_PUBLIC|MEMF_CLEAR)) {
  1394.                     strcpy(rsrc->phr_Lib.lib_Node.ln_Name,PATHHASH_RSRC);
  1395.                     if (rsrc->phr_Sema.ss_Link.ln_Name=AllocVec(strlen(PATHHASH_SEMA)+1,MEMF_PUBLIC|MEMF_CLEAR)) {
  1396.                         strcpy(rsrc->phr_Sema.ss_Link.ln_Name,PATHHASH_SEMA);
  1397.                         rsrc->phr_Sema.ss_Link.ln_Pri = 0;
  1398.                         AddSemaphore(&rsrc->phr_Sema);
  1399.                         AddResource(rsrc);
  1400.                         readin = TRUE;
  1401.                     }
  1402.                     else {
  1403.                         FreeVec(rsrc->phr_Lib.lib_Node.ln_Name);
  1404.                         FreeVec(rsrc);
  1405.                     }
  1406.                 }
  1407.                 else {
  1408.                     FreeVec(rsrc);
  1409.                 }
  1410.             }
  1411.         }
  1412.         if (rsrc) {
  1413.             rsrc->phr_Lib.lib_OpenCnt++;
  1414.             if (readin)
  1415.                 ObtainSemaphore(&rsrc->phr_Sema);
  1416.             else
  1417.                 ObtainSemaphoreShared(&rsrc->phr_Sema);
  1418.         }
  1419.         Permit();
  1420.  
  1421.         if (!rsrc) {
  1422.             printf("csh: cannot create resource\n");
  1423.             return 10;
  1424.         }
  1425.  
  1426.         /* clear old list -- if any */
  1427.         remove_local_pathhash();
  1428.  
  1429.         if (readin) {
  1430.             long hashlen = 0;
  1431.             if (fp=fopen(fname,"r")) {
  1432.                 while (fgets(buf,255,fp)) {
  1433.                     if (lf=strchr(buf,'\n')) {
  1434.                         *lf = '\0';
  1435.                     }
  1436.                     add_array_list(&prghash_list,&prghash_num,buf);
  1437.                     hashlen += strlen(buf)+1;
  1438.                 }
  1439.                 fclose(fp);
  1440.             }
  1441.             else
  1442.                 pError(fname);
  1443.             save_pathhash_to_mem(rsrc,hashlen);
  1444.         }
  1445.         else {
  1446.             load_pathhash_from_mem(rsrc);
  1447.         }
  1448.  
  1449.         Forbid();
  1450.         ReleaseSemaphore(&rsrc->phr_Sema);
  1451.         rsrc->phr_Lib.lib_OpenCnt--;
  1452.         Permit();
  1453.     }
  1454.     else if (options&4) {    /* output hash-list */
  1455.  
  1456.         for(i=0; !dobreak() && i<prghash_num; i++)
  1457.             printf("%s\n",prghash_list[i]);
  1458.     }
  1459.     else if (options&8) {    /* save hash-list */
  1460.         FILE *fp;
  1461.         char *fname;
  1462.  
  1463.         if (!(fname=get_var(LEVEL_SET,v_prghash))) {
  1464.             fprintf(stderr,"$_prghash unset\n");
  1465.             return 20;
  1466.         }
  1467.  
  1468.         if (fp=fopen(fname,"w")) {
  1469.             for(i=0; i<prghash_num; i++)
  1470.                 fprintf(fp,"%s\n",prghash_list[i]);
  1471.             fclose(fp);
  1472.         }
  1473.         else
  1474.             pError(fname);
  1475.  
  1476.     }
  1477.     else if (options&16) {    /* free global hash-list */
  1478.  
  1479.         if (!remove_global_pathhash())
  1480.             printf("csh: cannot clear, currently in use or does not exist\n");
  1481.     }
  1482.     else {
  1483.         BPTR lock;
  1484.         struct PathList *pl;
  1485.         struct FileInfoBlock *fib;
  1486.         char **path_list = NULL;
  1487.         long path_num = 0;
  1488.         long hashlen = 0;
  1489.         long slen;
  1490.  
  1491.         /* clear old list -- if any */
  1492.         remove_local_pathhash();
  1493.  
  1494.         Forbid();
  1495.         pl = (struct PathList *)BADDR(Mycli->cli_CommandDir);
  1496.         while (pl) {
  1497.             if (pl->pl_PathLock) {
  1498.                 if (NameFromLock(pl->pl_PathLock,buf,255L))
  1499.                     add_array_list(&path_list,&path_num,buf);
  1500.                 else
  1501.                     fprintf(stderr,"csh.do_rehash: NameFromLock() failed\n");
  1502.             }
  1503.             pl = (struct PathList *)BADDR(pl->pl_NextPath);
  1504.         }
  1505.         Permit();
  1506.  
  1507.         resolve_multiassign("C:",&path_list,&path_num);
  1508.  
  1509.         if (fib=AllocVec(sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) {
  1510.             for(i=0; !dobreak() && i<path_num; i++) {
  1511.                 if (lock=Lock(path_list[i],SHARED_LOCK)) {
  1512.                     if (Examine(lock,fib)) {
  1513.                         while (!dobreak() && ExNext(lock,fib)) {
  1514.                             if (fib->fib_DirEntryType<0 && (!(fib->fib_Protection&FIBF_EXECUTE) || fib->fib_Protection&FIBF_SCRIPT)) {
  1515.                                 slen = strlen(fib->fib_FileName);
  1516.                                 if (slen<5 || stricmp(fib->fib_FileName+slen-5,".info")!=0) {
  1517.                                     strcpy(buf,path_list[i]);
  1518.                                     if (AddPart(buf,fib->fib_FileName,255)) {
  1519.                                         add_array_list(&prghash_list,&prghash_num,buf);
  1520.                                         hashlen += strlen(buf)+1;
  1521.                                     }
  1522.                                     else {
  1523.                                         printf("path too long: %s -> %s\n",path_list[i],fib->fib_FileName);
  1524.                                     }
  1525.                                 }
  1526.                             }
  1527.                         }
  1528.                     }
  1529.                     UnLock(lock);
  1530.                 }
  1531.             }
  1532.             FreeVec(fib);
  1533.         }
  1534.  
  1535.         free_array_list(path_list,path_num);
  1536.  
  1537.         Forbid();
  1538.         if (!(rsrc = OpenResource(PATHHASH_RSRC))) {
  1539.             if (rsrc=AllocVec(sizeof(struct PathHashRsrc),MEMF_PUBLIC|MEMF_CLEAR)) {
  1540.                 rsrc->phr_Lib.lib_Node.ln_Type = NT_RESOURCE;
  1541.                 rsrc->phr_Lib.lib_Node.ln_Pri  = 0;
  1542.                 if (rsrc->phr_Lib.lib_Node.ln_Name=AllocVec(strlen(PATHHASH_RSRC)+1,MEMF_PUBLIC|MEMF_CLEAR)) {
  1543.                     strcpy(rsrc->phr_Lib.lib_Node.ln_Name,PATHHASH_RSRC);
  1544.                     if (rsrc->phr_Sema.ss_Link.ln_Name=AllocVec(strlen(PATHHASH_SEMA)+1,MEMF_PUBLIC|MEMF_CLEAR)) {
  1545.                         strcpy(rsrc->phr_Sema.ss_Link.ln_Name,PATHHASH_SEMA);
  1546.                         rsrc->phr_Sema.ss_Link.ln_Pri = 0;
  1547.                         AddSemaphore(&rsrc->phr_Sema);
  1548.                         AddResource(rsrc);
  1549.                     }
  1550.                     else {
  1551.                         FreeVec(rsrc->phr_Lib.lib_Node.ln_Name);
  1552.                         FreeVec(rsrc);
  1553.                     }
  1554.                 }
  1555.                 else {
  1556.                     FreeVec(rsrc);
  1557.                 }
  1558.             }
  1559.         }
  1560.         if (rsrc) {
  1561.             rsrc->phr_Lib.lib_OpenCnt++;
  1562.             ObtainSemaphore(&rsrc->phr_Sema);
  1563.         }
  1564.         Permit();
  1565.  
  1566.         if (!rsrc) {
  1567.             printf("csh: cannot create resource\n");
  1568.             return 10;
  1569.         }
  1570.  
  1571.         save_pathhash_to_mem(rsrc,hashlen);
  1572.  
  1573.         Forbid();
  1574.         ReleaseSemaphore(&rsrc->phr_Sema);
  1575.         rsrc->phr_Lib.lib_OpenCnt--;
  1576.         Permit();
  1577.     }
  1578.  
  1579.     return 0;
  1580. }
  1581.  
  1582.  
  1583.  
  1584. do_path( void )
  1585. {
  1586.     struct Process *proc;
  1587.     BPTR lock,dup_lock;
  1588.     long mycli,clinum,mincli,maxcli;
  1589.     struct PathList *pl,*new_pl,*old,*last;
  1590.     char buf[256];
  1591.     int i;
  1592.  
  1593.     if ( options&1 ) {
  1594.         long noram = 0;
  1595.         Forbid();
  1596.         mincli = 1;
  1597.         maxcli = MaxCli();
  1598.         mycli  = Myprocess->pr_TaskNum;
  1599.         if (!(options&2))
  1600.             mincli = maxcli = mycli;
  1601.         for (clinum = mincli; clinum<=maxcli; clinum++) {
  1602.             if (proc=FindCliProc(clinum)) {
  1603.                 pl = (struct PathList *)BADDR(CLI(proc)->cli_CommandDir);
  1604.                 while (pl) {
  1605.                     if (pl->pl_PathLock) {
  1606.                         UnLock(pl->pl_PathLock);
  1607.                     }
  1608.                     old = pl;
  1609.                     pl = (struct PathList *)BADDR(pl->pl_NextPath);
  1610.                     if (TypeOfMem(old) != 0)
  1611.                         DosFreeMem( old );
  1612.                     else
  1613.                         ++noram;
  1614.                 }
  1615.                 CLI(proc)->cli_CommandDir=NULL;
  1616.             }
  1617.         }
  1618.         Permit();
  1619.         if (noram>0) {
  1620.             fprintf(stderr,"%ld structure%s (%ld bytes) not freed, memory isn't in known RAM\n",
  1621.                     noram,
  1622.                     (noram>1) ? "s":"",
  1623.                     noram*sizeof(struct PathList));
  1624.         }
  1625.     } else if( ac==1 ) {
  1626.         char **dev_list=NULL;
  1627.         long dev_num=0,i;
  1628.         puts("Current dir");
  1629.         Forbid();
  1630.         pl = (struct PathList *)BADDR(Mycli->cli_CommandDir);
  1631.         while (pl) {
  1632.             if (pl->pl_PathLock) {
  1633.                 if (NameFromLock(pl->pl_PathLock,buf,255L))
  1634.                     add_array_list(&dev_list,&dev_num,buf);
  1635.                 else
  1636.                     fprintf(stderr,"csh.do_path: NameFromLock() failed\n");
  1637.             }
  1638.             pl = (struct PathList *)BADDR(pl->pl_NextPath);
  1639.         }
  1640.         Permit();
  1641.  
  1642.         for(i=0; !dobreak() && i<dev_num; i++)
  1643.             printf("%s\n",dev_list[i]);
  1644.         free_array_list(dev_list,dev_num);
  1645.  
  1646.         if (!dobreak())
  1647.             puts("C:");
  1648.         return 0;
  1649.     }
  1650.     for( i=1; i<ac; i++ ) {
  1651.         if( !(lock=Lock(av[i],ACCESS_READ)) ) {
  1652.             ierror(av[i],205);
  1653.             continue;
  1654.         }
  1655.         if( !isdir(av[i])) {
  1656.             ierror(av[i],212);
  1657.             UnLock(lock);
  1658.             continue;
  1659.         }
  1660.         Forbid();
  1661.         mincli = 1;
  1662.         maxcli = MaxCli();
  1663.         mycli  = Myprocess->pr_TaskNum;
  1664.         if (!(options&2))
  1665.             mincli = maxcli = mycli;
  1666.         for (clinum = mincli; clinum<=maxcli; clinum++) {
  1667.             if (proc=FindCliProc(clinum)) {
  1668.                 if (options&2)
  1669.                     dup_lock = DupLock(lock);
  1670.                 else
  1671.                     dup_lock = lock;
  1672.                 last = pl = (struct PathList *)BADDR(CLI(proc)->cli_CommandDir);
  1673.                 while (pl && dup_lock) {
  1674.                     last = pl;
  1675.                     if (pl->pl_PathLock) {
  1676.                         if (SameLock(pl->pl_PathLock,dup_lock)==LOCK_SAME) {
  1677.                             UnLock(dup_lock);
  1678.                             dup_lock=NULL;
  1679.                         }
  1680.                     }
  1681.                     pl = (struct PathList *)BADDR(pl->pl_NextPath);
  1682.                 }
  1683.                 if (dup_lock) {
  1684.                     if (new_pl=DosAllocMem( sizeof(struct PathList) )) {
  1685.                         new_pl->pl_NextPath = NULL;
  1686.                         new_pl->pl_PathLock = dup_lock;
  1687.                         if (last)
  1688.                             last->pl_NextPath = MKBADDR(new_pl);
  1689.                         else
  1690.                             CLI(proc)->cli_CommandDir = MKBADDR(new_pl);
  1691.                     }
  1692.                     else
  1693.                         UnLock(dup_lock);
  1694.                 }
  1695.             }
  1696.         }
  1697.         Permit();
  1698.         if (options&2)
  1699.             UnLock(lock);
  1700.     }
  1701.     return 0;
  1702. }
  1703.  
  1704. do_pri( void )
  1705. {
  1706.     int t, pri;
  1707.     struct Process *proc;
  1708.  
  1709.     t=(LONG)MaxCli();
  1710.     t=myatoi(av[1],0,t); if (atoierr) return 20;
  1711.     pri=myatoi(av[2],-128,127); if (atoierr) return 20;
  1712.     Forbid();
  1713.     proc=(t==0 ? Myprocess : FindCliProc((LONG)t));
  1714.     if (proc==NULL) fprintf(stderr, "process not found\n");
  1715.     else SetTaskPri((struct Task *)proc, (long)pri);
  1716.     Permit();
  1717.     return 0;
  1718. }
  1719.  
  1720. do_strleft( void )
  1721. {
  1722.     int n;
  1723.  
  1724.     n=posatoi(av[3]); if (atoierr) return 20;
  1725.     set_var_n(LEVEL_SET, av[1], av[2], n);
  1726.     return 0;
  1727. }
  1728.  
  1729. do_strright( void )
  1730. {
  1731.     int n, len=strlen(av[2]);
  1732.  
  1733.     n=posatoi(av[3]); if (atoierr) return 20;
  1734.     if( n>len ) n=len;
  1735.     set_var(LEVEL_SET, av[1], av[2]+len-n );
  1736.     return 0;
  1737. }
  1738.  
  1739. do_strmid( void )
  1740. {
  1741.     int n1, n2=999999, len=strlen(av[2]);
  1742.  
  1743.     n1=myatoi(av[3],1,999999)-1; if (atoierr) return 20;
  1744.     if (n1>len) n1=len;
  1745.     if (ac>4) {
  1746.         n2=posatoi(av[4]); if (atoierr) return 20;
  1747.     }
  1748.     set_var_n(LEVEL_SET, av[1], av[2]+n1, n2);
  1749.     return 0;
  1750. }
  1751.  
  1752. do_strlen( void )
  1753. {
  1754.     char buf[16];
  1755.  
  1756.     sprintf(buf,"%d",strlen(av[2]));
  1757.     set_var(LEVEL_SET, av[1], buf);
  1758.     return 0;
  1759. }
  1760.  
  1761. int atoierr;
  1762.  
  1763. myatoi(char *s,int mmin,int mmax)
  1764. {
  1765.     int n;
  1766.  
  1767.     atoierr=0;   /* GMD: initialise external flag! */
  1768.     n=atol(s);
  1769.  
  1770.     if (!isnum(s)) {   /* AMK: IoErr() replaced by isnum() */
  1771.         atoierr=1;
  1772.         ierror(s,511);
  1773.     }
  1774.     else if (n<mmin || n>mmax) {
  1775.         /*fprintf( stderr, "%s(%d) not in (%d,%d)\n",s,n,mmin,mmax );*/
  1776.         fprintf( stderr, "%s not in (%d,%d)\n",s,mmin,mmax );
  1777.         atoierr=1; n=mmin;
  1778.     }
  1779.     return n;
  1780. }
  1781.  
  1782. unlatoi(char *s)
  1783. {
  1784.     int n=atol(s);
  1785.     atoierr=0;
  1786.     if (!isnum(s)) {   /* AMK: IoErr() replaced by isnum() */
  1787.         atoierr=1;
  1788.         ierror(s,511);
  1789.         n=0;
  1790.     }
  1791.     return n;
  1792. }
  1793.  
  1794. posatoi(char *s)
  1795. {
  1796.     int n=atol(s);
  1797.     atoierr=0;
  1798.     if (!isnum(s)) {   /* AMK: IoErr() replaced by isnum() */
  1799.         atoierr=1;
  1800.         ierror(s,511);
  1801.         n=0;
  1802.     }
  1803.     else if (n<0 )
  1804.         atoierr=1, n=0, fprintf( stderr, "%s must be positive\n",s );
  1805.     return n;
  1806. }
  1807.  
  1808.  
  1809. do_fltlower( void )
  1810. {
  1811.     return line_filter( strlwr );
  1812. }
  1813.  
  1814. do_fltupper( void )
  1815. {
  1816.     return line_filter( strupr );
  1817. }
  1818.  
  1819. #if 0
  1820. char *
  1821. stripcr( char *get )
  1822. {
  1823.     char *old=get, *put;
  1824.  
  1825.     for( put=get; *get; get++ )
  1826.         if( *get!=13 )
  1827.             *put++=*get;
  1828.     *put++=0;
  1829.     return old;
  1830. }
  1831.  
  1832. do_fltstripcr( void )
  1833. {
  1834.     return line_filter( stripcr );
  1835. }
  1836. #endif
  1837.  
  1838. static int
  1839. line_filter( char *(*func)( char * ) )
  1840. {
  1841.     char buf[256];
  1842.  
  1843.     while (!CHECKBREAK() && myfgets(buf,stdin))
  1844.         puts((*func)(buf));
  1845.     return 0;
  1846. }
  1847.  
  1848. int
  1849. do_linecnt( void )
  1850. {
  1851.     int count=0;
  1852.     char buf[256];
  1853.  
  1854.     while (!CHECKBREAK() && fgets(buf,255,stdin)) ++count;
  1855.     printf("%d lines\n",count);
  1856.     return 0;
  1857. }
  1858.  
  1859. int
  1860. do_uniq( void )
  1861. {
  1862.     int firstline=1;
  1863.     char buf[256], oldbuf[256];
  1864.  
  1865.     while (!CHECKBREAK() && myfgets(buf,stdin)) {
  1866.         if ( firstline || strcmp(buf, oldbuf)) {
  1867.             strcpy(oldbuf, buf);
  1868.             puts(buf);
  1869.         }
  1870.         firstline=0;
  1871.     }
  1872.     return 0;
  1873. }
  1874.  
  1875.  
  1876. #define RXFB_RESULT  17
  1877. #define RXCOMM    0x01000000
  1878.  
  1879. static struct rexxmsg {
  1880.     struct Message rm_Node;             /* EXEC message structure        */
  1881.     APTR     rm_TaskBlock;              /* global structure (private)    */
  1882.     APTR     rm_LibBase;                /* library base (private)        */
  1883.     LONG     rm_Action;                 /* command (action) code         */
  1884.     LONG     rm_Result1;                /* primary result (return code)  */
  1885.     LONG     rm_Result2;                /* secondary result              */
  1886.     STRPTR   rm_Args[16];               /* argument block (ARG0-ARG15)   */
  1887.  
  1888.     struct MsgPort *rm_PassPort;        /* forwarding port               */
  1889.     STRPTR   rm_CommAddr;               /* host address (port name)      */
  1890.     STRPTR   rm_FileExt;                /* file extension                */
  1891.     LONG     rm_Stdin;                  /* input stream (filehandle)     */
  1892.     LONG     rm_Stdout;                 /* output stream (filehandle)    */
  1893.     LONG     rm_avail;                  /* future expansion              */
  1894. } mymsg;                                /* size: 128 bytes               */
  1895.  
  1896.  
  1897. do_rxsend( char *avline )
  1898. {
  1899.     int i, ret=0;
  1900.     long result;
  1901.     struct MsgPort *port, *reply;
  1902.     long len;
  1903.     char buf[20], *resptr;
  1904.  
  1905.     if (!(port = (struct MsgPort *)FindPort(av[1])))
  1906.         { fprintf(stderr, "No port %s!\n", av[1]); return 20; }
  1907.     mymsg.rm_Node.mn_Node.ln_Type = NT_MESSAGE;
  1908.     mymsg.rm_Node.mn_Length = sizeof(struct rexxmsg);
  1909.     mymsg.rm_Action = RXCOMM | (options&1 ? 1L << RXFB_RESULT : 0);
  1910.     if (!(reply = CreateMsgPort())) {
  1911.         fprintf(stderr, "No reply port\n");
  1912.         return 20;
  1913.     }
  1914.     mymsg.rm_Node.mn_ReplyPort = reply;
  1915.  
  1916.     if( options&2 )
  1917.         av[2]=compile_av( av,2,ac,' ',0), ac=3;
  1918.     for ( i=2; i<ac; i++) {
  1919.         mymsg.rm_Args[0] = av[i];
  1920.         mymsg.rm_Result2 = 0;        /* clear out the last result. */
  1921.         PutMsg(port, &mymsg.rm_Node);
  1922.  
  1923.         Wait( 1<<reply->mp_SigBit | SIGBREAKF_CTRL_C );
  1924.  
  1925.         if( CHECKBREAK() ) {
  1926.             ret=5;
  1927.             break;
  1928.         }
  1929.  
  1930.         if (options&1) {
  1931.             if( (result=mymsg.rm_Result2)<1000000 ) { /* like AREXX */
  1932.                 sprintf(buf,"%d",result);              
  1933.                 set_var(LEVEL_SET,v_result,buf);
  1934.             } else {
  1935.                 resptr=(char *)(result-4);
  1936.                 len=*(long *)resptr;
  1937.                 memmove(resptr,resptr+4,len);  /* Null terminate */
  1938.                 resptr[len]=0;      
  1939.                 set_var(LEVEL_SET,v_result,resptr);
  1940.                 FreeMem(resptr, len+4 );
  1941.             }
  1942.         } else 
  1943.             unset_var( LEVEL_SET, v_result );
  1944.     }
  1945.     if( options&2 )
  1946.         free( av[2] );
  1947.  
  1948.     if (reply) DeleteMsgPort(reply);
  1949.     return ret;
  1950. }
  1951.  
  1952. static char *rxreturn;
  1953.  
  1954. do_rxrec( void )
  1955. {
  1956.     struct MsgPort *port;
  1957.     struct rexxmsg *msg;
  1958.     char *portname, *str;
  1959.  
  1960.     if (ac > 1)
  1961.         portname=av[1];
  1962.     else
  1963.         portname="rexx_csh";
  1964.  
  1965.     if (!(port=CreateMsgPort())) {
  1966.         fprintf(stderr, "Can't have MsgPort %s\n", portname);
  1967.         return 20;
  1968.     }
  1969.     port->mp_Node.ln_Name = portname;
  1970.     port->mp_Node.ln_Pri  = 0;
  1971.     AddPort(port);
  1972.     for (;;) {
  1973.         WaitPort(port);
  1974.         while (msg=(struct rexxmsg *)GetMsg(port)) {
  1975.             if ( ! stricmp(msg->rm_Args[0], "bye")) {
  1976.                 ReplyMsg((struct Message *)msg);
  1977.                 RemPort(port);
  1978.                 DeleteMsgPort(port);
  1979.                 return 0;
  1980.             }
  1981.             rxreturn=NULL;
  1982.             exec_command(msg->rm_Args[0]);
  1983.             if (msg->rm_Action & (1L << RXFB_RESULT)) {
  1984.                 if( rxreturn ) {
  1985.                     str= SAllocMem( strlen( rxreturn )+5 , 0 );
  1986.                     *(long *)str=strlen( rxreturn );
  1987.                     strcpy( str+4, rxreturn );
  1988.                     msg->rm_Result2=(long)str;
  1989.                 } else {
  1990.                     str = get_var(LEVEL_SET, v_lasterr);
  1991.                     msg->rm_Result2=(str) ? atoi(str) : 20;
  1992.                 }
  1993.             }
  1994.             ReplyMsg((struct Message *)msg);
  1995.         }
  1996.     }
  1997. }
  1998.  
  1999. int
  2000. do_waitport( void )
  2001. {
  2002.     int count=4*10;
  2003.     struct MsgPort *port=NULL;
  2004.  
  2005.     if( ac==3 ) 
  2006.         { count=2*myatoi(av[2],0, 32000); if( atoierr ) return 20; }
  2007.  
  2008.     while( --count>=0 && !(port=FindPort(av[1])) && !dobreak() )
  2009.         Delay(12);
  2010.  
  2011.     return port ? 0 : 20;
  2012. }
  2013.  
  2014. int
  2015. do_rxreturn( void )
  2016. {
  2017.     rxreturn=compile_av( av, 1, ac, ' ', 1 );
  2018.     return 0;
  2019. }
  2020.  
  2021. do_ascii( void )
  2022. {
  2023.     int x=1, y, c, c1, t;
  2024.     char *fmt1=" %3d %c%c |", *fmt2=" %4d";
  2025.  
  2026.     if( options&1 ) fmt1=" %3o %c%c |", fmt2="%4o";
  2027.     if( options&2 ) fmt1=" %3x %c%c |", fmt2="%4x";
  2028.     if( ac==x )
  2029.         for( y=0; y<32 && !dobreak(); y++ ) {
  2030.             printf("|");
  2031.             for( x=0; x<8; x++ ) {
  2032.                 c1=c=y+32*x; t=' ';
  2033.                 if( c<32 ) t='^', c1+=64;
  2034.                 printf(fmt1,c, t, c1<128 || c1>=160?c1:'.');
  2035.             }
  2036.             printf("\n");
  2037.         }
  2038.     else 
  2039.         for( ; x<ac && !dobreak(); x++ ) {
  2040.             for( y=0; y<strlen(av[x]); y++ )
  2041.                 printf(fmt2,av[x][y]);
  2042.             printf("\n");
  2043.         }
  2044.     return 0;
  2045. }
  2046.  
  2047. void
  2048. appendslash( char *path )
  2049. {
  2050.     int c;
  2051.  
  2052.     if( (c=path[strlen(path)-1]) !='/' && c!=':' )
  2053.         strcat(path,"/");
  2054. }
  2055.  
  2056. static void
  2057. whereis( char *path, char *file )
  2058. {
  2059.     char **eav, buf[100];
  2060.     int  eac, j;
  2061.  
  2062.     buf[0]=0;
  2063.     if( path ) {
  2064.         strcpy(buf,path);
  2065.         appendslash(buf);
  2066.     }
  2067.     strcat(buf,".../");
  2068.     strcat(buf,file);
  2069.     if( !index( file, '*' ) && !index( file, '?') )
  2070.         strcat(buf,"*");
  2071.     if(eav=expand(buf,&eac)) {
  2072.         for( j=0; j<eac && !dobreak(); j++ )
  2073.             printf("%s\n",eav[j]);
  2074.         free_expand(eav);
  2075.     }
  2076. }
  2077.  
  2078. do_whereis( void )
  2079. {
  2080.     char buf[200], *prev, *devs;
  2081.     int i;
  2082.  
  2083.     if( index( av[1],':') || index( av[1],'/' ) )
  2084.         { fprintf(stderr,"No paths please\n"); return 20; };
  2085.  
  2086.     if( options&1 ) {
  2087.         Myprocess->pr_WindowPtr = (APTR)(-1);
  2088.         get_drives( devs=buf );
  2089.         do {
  2090.             prev=devs; devs=index(devs,0xA0);
  2091.             if( devs ) *devs++=0; 
  2092.             whereis( prev, av[1] );
  2093.         } while( devs );
  2094.         Myprocess->pr_WindowPtr = o_noreq ? (APTR) -1L : Mywindow;
  2095.     } else if( ac==2 ) {
  2096.         whereis( NULL, av[1] );
  2097.     } else {
  2098.         for( i=2; i<ac; i++ ) {
  2099.             strcpy(buf,av[i]);
  2100.             appendslash( buf );
  2101.             whereis( buf, av[1] );
  2102.         }
  2103.     }
  2104.     return 0;
  2105. }
  2106.  
  2107. do_usage( void )
  2108. {
  2109.     int i;
  2110.  
  2111.     if( ac==1 ) {
  2112.         printf("Usage: usage [command...command]\n");
  2113.         printf("[ ]=option   [ | ]=choice   { }=repetition   name...name=1 or more names\n");
  2114.     } else
  2115.         for( i=1; i<ac; i++ )
  2116.             show_usage( av[i] );
  2117.     return 0;
  2118. }
  2119.  
  2120.  
  2121.  
  2122. /* these defines are new in OS 3.x */
  2123. #ifndef WA_NewLookMenus
  2124. #define WA_NewLookMenus (WA_Dummy + 0x30)
  2125. #endif
  2126. #ifndef GTMN_NewLookMenus
  2127. #define GTMN_NewLookMenus GT_TagBase+67
  2128. #endif
  2129. #ifndef WFLG_NEWLOOKMENUS
  2130. #define WFLG_NEWLOOKMENUS 0x00200000
  2131. #endif
  2132.  
  2133.  
  2134.  
  2135. static struct NewMenu *NewMenus = NULL;
  2136. static int AnzMenus = 0, AnzItems = 1;
  2137. static APTR *visualInfo = NULL;
  2138. static struct Menu *menuStrip = NULL;
  2139. static char *fontName = NULL;
  2140. static struct TextAttr textAttr;
  2141. static struct TextFont *textFont = NULL;
  2142.  
  2143. char *MenuCommand[MAXMENUS][MAXMENUITEMS];
  2144.  
  2145. do_menu( void )
  2146. {
  2147.     if( o_nowindow )
  2148.         return 5;
  2149.  
  2150.     if( options&1 )
  2151.         remove_menu();
  2152.  
  2153.     if( ac==2 )
  2154.         show_usage( NULL );
  2155.     else if( AnzMenus<MAXMENUS && ac!=1)
  2156.         install_menu( av+1, ac-1 );
  2157.  
  2158.     set_menu();
  2159.     return 0;
  2160. }
  2161.  
  2162. static void
  2163. install_menu( char *mav[], int mac )
  2164. {
  2165.     char *p, *com;
  2166.     long msize;
  2167.     struct NewMenu *new_NewMenus;
  2168.     int i;
  2169.  
  2170.     if (o_nowindow || !Mywindow)
  2171.         return;
  2172.  
  2173.     /* mac holds number of items, including title which counts as item */
  2174.  
  2175.     if (mac>MAXMENUITEMS)
  2176.         mac=MAXMENUITEMS;
  2177.  
  2178.     ClearMenuStrip( Mywindow );
  2179.     if (menuStrip) FreeMenus(menuStrip);
  2180.     if (visualInfo) FreeVisualInfo(visualInfo);
  2181.     Delay(3);
  2182.  
  2183.     msize = sizeof(struct NewMenu) * (mac+1 + AnzItems-1);    /* one extra 'end' item */
  2184.     new_NewMenus = salloc(msize);
  2185.     memset(new_NewMenus,0,msize);
  2186.     if (NewMenus) {
  2187.         memcpy(new_NewMenus,NewMenus,sizeof(struct NewMenu)*(AnzItems-1));
  2188.         free(NewMenus);
  2189.     }
  2190.     else {
  2191.         int i,j;
  2192.         for (i=0; i<MAXMENUS; i++)
  2193.             for (j=0; j<MAXMENUITEMS; j++)
  2194.                 MenuCommand[i][j] = NULL;
  2195.     }
  2196.     NewMenus = new_NewMenus;
  2197.  
  2198.     NewMenus[AnzItems-1].nm_Type  = NM_TITLE;
  2199.     NewMenus[AnzItems-1].nm_Label = strcpy(salloc(strlen(mav[0])+1),mav[0]);
  2200.  
  2201.     for( i=1; i<mac; i++) {
  2202.         com=NULL;
  2203.         if( p=index(mav[i],',')) {
  2204.             *p=0; com=++p;
  2205.             if( p=index(com,',')) {
  2206.                 *p=0;
  2207.                 NewMenus[AnzItems].nm_CommKey = strdup(++p);
  2208.             }
  2209.         }
  2210.  
  2211.         if( !com || !*com) {
  2212.             com=strcpy(salloc(strlen(mav[i])+2),mav[i]);
  2213.             MenuCommand[AnzMenus][i-1]=com;
  2214.             com+=strlen(com);
  2215.             *com++=13;
  2216.             *com=0;
  2217.         } else {
  2218.             MenuCommand[AnzMenus][i-1]=strcpy(salloc(strlen(com)+1),com);
  2219.         }
  2220.  
  2221.         NewMenus[AnzItems].nm_Type  = NM_ITEM;
  2222.         NewMenus[AnzItems].nm_Label = strcpy(salloc(strlen(mav[i])+2),mav[i]);
  2223.  
  2224.         AnzItems++;
  2225.     }
  2226.  
  2227.     AnzMenus++;
  2228.     NewMenus[AnzItems++].nm_Type = NM_END;
  2229.  
  2230.     if (!(visualInfo=GetVisualInfo(Mywindow->WScreen,TAG_END))) {
  2231.         printf("no visual info\n");
  2232.         free(NewMenus);
  2233.     }
  2234.  
  2235.     if (!(menuStrip=CreateMenus(NewMenus,TAG_END))) {
  2236.         printf("no create menus\n");
  2237.         FreeVisualInfo(visualInfo);
  2238.         free(NewMenus);
  2239.     }
  2240.  
  2241.     /* do we want a monospaced (non-proportional) font? */
  2242.     if (options&2 && !textFont && AnzMenus<=1) {
  2243.         Forbid();
  2244.         if (GfxBase->DefaultFont) {
  2245.             textAttr.ta_Name = fontName = strdup(GfxBase->DefaultFont->tf_Message.mn_Node.ln_Name);
  2246.             textAttr.ta_YSize = GfxBase->DefaultFont->tf_YSize;
  2247.         }
  2248.         else {
  2249.             textAttr.ta_Name  = "topaz.font";
  2250.             textAttr.ta_YSize = 8;
  2251.         }
  2252.         Permit();
  2253.         textAttr.ta_Style = FS_NORMAL;
  2254.         textAttr.ta_Flags = 0;
  2255.         if (textAttr.ta_Name)
  2256.             textFont = OpenDiskFont(&textAttr);
  2257.     }
  2258.  
  2259. /*
  2260.     if (!LayoutMenus(menuStrip,visualInfo,
  2261.                 textFont==NULL ? TAG_IGNORE : GTMN_TextAttr, &textAttr,
  2262.                 TAG_END))
  2263.     {
  2264. */
  2265.     if (!LayoutMenus(menuStrip,visualInfo,
  2266.                 Mywindow->Flags&WFLG_NEWLOOKMENUS ? GTMN_NewLookMenus : TAG_IGNORE, TRUE,
  2267.                 textFont==NULL ? TAG_IGNORE : GTMN_TextAttr, &textAttr,
  2268.                 TAG_END))
  2269.     {
  2270.  
  2271.         printf("no layout menus\n");
  2272.         FreeMenus(menuStrip);
  2273.         FreeVisualInfo(visualInfo);
  2274.         free(NewMenus);
  2275.     }
  2276.  
  2277.     return;
  2278. }
  2279.  
  2280. void remove_menu()
  2281. {
  2282.     if (AnzMenus>0) {
  2283.         struct NewMenu *nm;
  2284.         int i,j;
  2285.  
  2286.         for (i=0; i<MAXMENUS; i++) {
  2287.             for (j=0 ;j<MAXMENUITEMS; j++)
  2288.                 if (MenuCommand[i][j]) {
  2289.                     free(MenuCommand[i][j]);
  2290.                     MenuCommand[i][j] = NULL;
  2291.                 }
  2292.         }
  2293.  
  2294.         for (nm=NewMenus; nm->nm_Type!=NM_END; nm++) {
  2295.             if (nm->nm_Label) {
  2296.                 free(nm->nm_Label);
  2297.                 nm->nm_Label = NULL;
  2298.             }
  2299.             if (nm->nm_CommKey) {
  2300.                 free(nm->nm_CommKey);
  2301.                 nm->nm_CommKey = NULL;
  2302.             }
  2303.         }
  2304.  
  2305.         AnzMenus=0;
  2306.         set_menu();
  2307.     }
  2308. }
  2309.  
  2310. void set_menu()
  2311. {
  2312.     if (o_nowindow || !Mywindow)
  2313.         return;
  2314.  
  2315.     if (AnzMenus>0)
  2316.         SetMenuStrip(Mywindow,menuStrip);
  2317.     else {
  2318.         ClearMenuStrip(Mywindow);
  2319.         FreeMenus(menuStrip);
  2320.         FreeVisualInfo(visualInfo);
  2321.         free(NewMenus);
  2322.         menuStrip  = NULL;
  2323.         visualInfo = NULL;
  2324.         NewMenus   = NULL;
  2325.         AnzMenus = 0;
  2326.         AnzItems = 1;
  2327.         if (textFont) {
  2328.             CloseFont(textFont);
  2329.             textFont = NULL;
  2330.         }
  2331.         if (fontName) {
  2332.             free(fontName);
  2333.             fontName = NULL;
  2334.         }
  2335.     }
  2336.  
  2337.     Delay(3);
  2338. }
  2339.  
  2340.  
  2341. #if 0
  2342. int NumMenus;
  2343.  
  2344. static struct Menu DefaultMenu= {0, 0,0,TITWID,10, MENUENABLED,0,0};
  2345. static struct IntuiText DefaultIntuiText= {0,1,JAM2, 1,1,NULL,0,0};
  2346. static struct MenuItem DefaultMenuItem=
  2347.   {0, 0,0,ITEWID,0, HIGHCOMP|ITEMTEXT|ITEMENABLED,0,0,0,0,0,0};
  2348.  
  2349. struct Menu Menus[10];
  2350. char *MenuCommand[MAXMENUS][MAXMENUITEMS];
  2351.  
  2352. static void
  2353. install_menu( char *mav[], int mac )
  2354. {
  2355.     struct TextAttr *ta;
  2356.     struct Menu *m;
  2357.     struct MenuItem *mi, **pmi;
  2358.     struct IntuiText *it;
  2359.     int y, i, fonthei;
  2360.     char *p, *com;
  2361.  
  2362.     if( o_nowindow || !Mywindow )
  2363.         return;
  2364.  
  2365.     if( mac>=MAXMENUITEMS )
  2366.         mac=MAXMENUITEMS-1;
  2367.  
  2368.     ClearMenuStrip( Mywindow );
  2369.     Delay(3);
  2370.  
  2371.     if( NumMenus )
  2372.         Menus[NumMenus-1].NextMenu=Menus+NumMenus;
  2373.     m  =&Menus[NumMenus];
  2374.     *m =DefaultMenu;
  2375.     m->LeftEdge  = NumMenus*TITWID;
  2376.     m->MenuName  = strcpy(salloc(strlen(mav[0])+1),mav[0]);
  2377.     if( strlen(m->MenuName)>TITWID/8 )
  2378.         m->MenuName[TITWID/8+1]=0;
  2379.     DefaultIntuiText.ITextFont=ta=Mywindow->WScreen->Font;
  2380.     DefaultMenuItem.Height=2+(fonthei=ta->ta_YSize);
  2381.  
  2382.     y=0;
  2383.     pmi=&m->FirstItem;
  2384.     for( i=1; i<mac; i++) {
  2385.         it =(void *)salloc(sizeof(struct IntuiText));
  2386.         *it=DefaultIntuiText;
  2387.         mi =(void *)salloc(sizeof(struct MenuItem ));
  2388.         *mi=DefaultMenuItem;
  2389.  
  2390.         com=NULL;
  2391.         if( p=index(mav[i],',')) {
  2392.             *p=0; com=++p;
  2393.             if( p=index(com,',')) {
  2394.                 *p=0;
  2395.                 mi->Command=p[1];
  2396.                 mi->Flags |=COMMSEQ;
  2397.             }
  2398.         }
  2399.  
  2400.         if( !com || !*com) {
  2401.             com=strcpy(salloc(strlen(mav[i])+2),mav[i]);
  2402.             MenuCommand[NumMenus][i-1]=com;
  2403.             com+=strlen(com);
  2404.             *com++=13;
  2405.             *com=0;
  2406.         } else {
  2407.             MenuCommand[NumMenus][i-1]=strcpy(salloc(strlen(com)+1),com);
  2408.         }
  2409.  
  2410.         it->IText=(UBYTE *)strcpy(salloc(strlen(mav[i])+2),mav[i]);
  2411.  
  2412.         *pmi= mi;
  2413.         pmi = &mi->NextItem;
  2414.         mi->TopEdge = y;
  2415.         mi->ItemFill= (APTR)it;
  2416.  
  2417.         y+=DefaultMenuItem.Height;
  2418.     }
  2419.  
  2420.     NumMenus++;
  2421. MError:
  2422.     return;
  2423. }
  2424.  
  2425. void remove_menu()
  2426. {
  2427.     if (NumMenus>0) {
  2428.         struct MenuItem *mi, *nextmi;
  2429.         int i,j;
  2430.  
  2431.         for( i=0; i<NumMenus; i++ ) {
  2432.             for( mi=Menus[i].FirstItem,j=0 ; mi; mi=nextmi,j++ ) {
  2433.                 free( ((struct IntuiText *)mi->ItemFill)->IText );
  2434.                 free( ((struct IntuiText *)mi->ItemFill) );
  2435.                 nextmi=mi->NextItem;
  2436.                 free(mi);
  2437.                 free(MenuCommand[i][j]);
  2438.             }
  2439.         }
  2440.  
  2441.         NumMenus=0;
  2442.         set_menu();
  2443.     }
  2444. }
  2445.  
  2446. void set_menu()
  2447. {
  2448.     if (o_nowindow || !Mywindow)
  2449.         return;
  2450.  
  2451.     if (NumMenus>0)
  2452.         SetMenuStrip(Mywindow,Menus);
  2453.     else
  2454.         ClearMenuStrip(Mywindow);
  2455.  
  2456.     Delay(3);
  2457. }
  2458. #endif
  2459.  
  2460. int
  2461. do_getenv( void )
  2462. {
  2463.     char buf[256], *val=buf;
  2464.  
  2465.     if( ac!=3 && ac!=2 ) {
  2466.         show_usage( NULL );
  2467.         return 20;
  2468.     }
  2469.     /* AMK: OS20-GetVar replaces ARP-Getenv */
  2470.     if( GetVar(av[ac-1],buf,256,GVF_GLOBAL_ONLY|GVF_BINARY_VAR) < 0L )
  2471.         val="";
  2472.  
  2473.     if( ac==2 )
  2474.         printf( "%s\n", val );
  2475.     else
  2476.         set_var( LEVEL_SET, av[1], val );
  2477.     return 0;
  2478. }
  2479.  
  2480. int
  2481. do_setenv( void )
  2482. {
  2483.     if( ac!=3 ) {
  2484.         show_usage( NULL );
  2485.         return 20;
  2486.     } else
  2487.         setenv( av[1], av[2] );
  2488.     return 0;
  2489. }
  2490.  
  2491. char **
  2492. read_name( char *name, int *ac )
  2493. {
  2494.     FILE *file;
  2495.     char **av=NULL;
  2496.  
  2497.     *ac=0;
  2498.     if( file=name ? fopen( name, "r") : stdin ) {
  2499.         av=read_file( file, ac );
  2500.         if( name ) fclose( file );
  2501.     } else 
  2502.         pError( name );
  2503.     return av;
  2504. }
  2505.  
  2506.  
  2507. char **
  2508. read_file( FILE *file, int *ac )
  2509. {
  2510.     int buflen=4096, lines=0, i, offs, got=0;
  2511.     char *buf, *tmp, *ptr, **lineptr;
  2512.  
  2513.     if( !(buf=ptr=DosAllocMem( buflen )))
  2514.         goto error;
  2515.     do {
  2516.         while( ptr+400 < buf+buflen && (got=myfgets(ptr, file)) && !dobreak())
  2517.             ptr+=strlen(ptr)+1, lines++;
  2518.         if( ptr+256 < buf+buflen ) {
  2519.             offs=ptr-buf;
  2520.             if( !(tmp=DosAllocMem( buflen*2 )))
  2521.                 goto error;
  2522.             memcpy( tmp, buf, buflen );
  2523.             DosFreeMem( buf );
  2524.             buflen*=2, buf=tmp;
  2525.             ptr=buf+offs;
  2526.         }
  2527.     } while( got && !dobreak());
  2528.     if( !(lineptr=(char **)DosAllocMem( (lines+1)*sizeof( char * ))))
  2529.         goto error;
  2530.     *lineptr++=buf;
  2531.     for( ptr=buf, i=0; i<lines; i++ ) {
  2532.         lineptr[i]=ptr;
  2533.         ptr+=strlen(ptr)+1;
  2534.     }
  2535.     *ac=lines;
  2536.     return lineptr;
  2537.  
  2538. error:
  2539.     if( buf ) DosFreeMem( buf );
  2540.     fprintf( stderr, "Out of memory\n" );
  2541.     *ac=0;
  2542.     return NULL;
  2543. }
  2544.  
  2545. void
  2546. free_file( ptr )
  2547.     char **ptr;
  2548. {
  2549.     if( ptr-- ) {
  2550.         if( *ptr )
  2551.             DosFreeMem( *ptr );
  2552.         DosFreeMem(ptr);
  2553.     }
  2554. }
  2555.  
  2556.  
  2557. do_qsort( void )
  2558. {
  2559.     char **lineptr;
  2560.     int  lines, i;
  2561.  
  2562.     if( ac==1 ) {
  2563.         lineptr=read_file( stdin, &lines);
  2564.         DirQuickSort( lineptr, lines, (options&2) ? cmp_case : cmp, options&1, 0 );
  2565.         prepscroll(0);
  2566.         for( i=0; i<lines && !dobreak(); i++ ) {
  2567.             quickscroll();
  2568.             puts( lineptr[i] );
  2569.         }
  2570.         free_file( lineptr );
  2571.     } else
  2572.         ierror( NULL,506 );
  2573.     return 0;
  2574. }
  2575.  
  2576. extern int w_width;
  2577.  
  2578. do_truncate( void )
  2579. {
  2580.     char buf[256];
  2581.     int  w=newwidth(), c;
  2582.     char *ptr;
  2583.  
  2584.     if( ac==2 )
  2585.         w=atoi( av[1] );
  2586.  
  2587.     prepscroll(0);
  2588.     while( myfgets(buf,stdin) && !dobreak() ) {
  2589.         for( c=0, ptr=buf; *ptr && c<w; ptr++ )
  2590.             if( *ptr=='\t' )
  2591.                 c+=8-(c&7);
  2592.             else if( *ptr==27 ) {
  2593.                 while( *ptr<'@' )
  2594.                     ptr++;
  2595.             } else 
  2596.                 c++;
  2597.         *ptr=0;
  2598.         quickscroll();
  2599.         puts(buf);
  2600.     }
  2601.     return 0;
  2602. }
  2603.  
  2604. int
  2605. do_readfile( void )
  2606. {
  2607.     char **rav, *str=NULL, *file=NULL;
  2608.     int rac;
  2609.  
  2610.     if( ac>2 ) file=av[2];
  2611.     if( rav=read_name( file, &rac ) ) { 
  2612.         if( str= compile_av( rav, 0, rac, 0xA0, 0 ) )
  2613.             set_var( LEVEL_SET, av[1], str );
  2614.         free_file( rav );
  2615.     }
  2616.     return str ? 0 : 20;
  2617. }
  2618.  
  2619. void
  2620. foreach( char **s, int (*func)(char *s) )
  2621. {
  2622.     char *str;
  2623.  
  2624.     for( ;; ) {
  2625.         str=*s;
  2626.         if( !(*s=index(*s,0xA0)))
  2627.             break;
  2628.         **s=0;
  2629.         (*func)(str);
  2630.         *(*s)++=0xA0;
  2631.         if( breakcheck())
  2632.             return;
  2633.     }
  2634.     (*func)(str);
  2635. }
  2636.  
  2637. int
  2638. do_writefile( void )
  2639. {
  2640.     char *ptr;
  2641.  
  2642.     if( !(ptr=get_var(LEVEL_SET,av[1])))
  2643.         { fprintf(stderr,"Undefined variable %s\n",av[1]); return 20; }
  2644.  
  2645.     foreach( &ptr, puts );
  2646.  
  2647.     return 0;
  2648. }
  2649.  
  2650. int
  2651. do_split( void )
  2652. {
  2653.     int i;
  2654.     char *val, *gap, *oldval;
  2655.  
  2656.     if( !(val=get_var( LEVEL_SET, av[1] )))
  2657.         { fprintf( stderr, "undefined variable %s\n", av[1] ); return 20; }
  2658.     oldval=val=strcpy(salloc(strlen(val)+1),val);
  2659.     for( i=2; i<ac-1; i++ ) {
  2660.         if( gap=index(val,0xA0 )) *gap=0;
  2661.         set_var( LEVEL_SET, av[i], val );
  2662.         val="";
  2663.         if( gap ) *gap=0xA0, val=gap+1;
  2664.     }
  2665.     set_var( LEVEL_SET, av[ac-1], val );
  2666.     free(oldval);
  2667.     return 0;
  2668. }
  2669.  
  2670. char *
  2671. copyof( char *str )
  2672. {
  2673.     return strcpy(salloc(strlen(str)+1),str);
  2674. }
  2675.  
  2676. int
  2677. do_class( char *avline )
  2678. {
  2679.     CLASS *new;
  2680.  
  2681.     if( options&1 ) {
  2682.         avline=next_word(avline);
  2683.         for( new=CRoot,CRoot=NULL; new; new=new->next )
  2684.             Free(new);
  2685.     }
  2686.  
  2687.     if( ac==1 ) {
  2688.         for( new=CRoot; new; new=new->next )
  2689.             printf("%s\n",new->name);
  2690.         return 0;
  2691.     }
  2692.  
  2693.     avline=next_word(avline);
  2694.     if(!(new=malloc( strlen(avline)+5)))
  2695.         ierror( NULL, 512 );
  2696.     else {
  2697.         new->next=NULL;
  2698.         strcpy( new->name,avline );
  2699.         if( CRoot )
  2700.             LastCRoot->next=new;
  2701.         else 
  2702.             CRoot=new;
  2703.         LastCRoot=new;
  2704.     }
  2705.     return 0;
  2706. }
  2707.  
  2708. do_getcl( void )
  2709. {
  2710.     char *s=getclass(av[1]);
  2711.     if( s ) printf("%s\n",s);
  2712.     return 0;
  2713. }
  2714.  
  2715. do_action( char *argline )
  2716. {
  2717.     char *args, err;
  2718.     int abort=options&1;
  2719.  
  2720.     args=compile_av( av,3,ac,' ',0 );
  2721.     err=doaction(av[2],av[1],args);
  2722.     if( !abort )
  2723.         if( err==9 )     ierror(av[2], 205 );
  2724.         else if(err==10) fprintf(stderr,"Can't identify %s\n", av[2] );
  2725.         else if(err==11) fprintf(stderr,"Can't '%s' this file\n",av[1] );
  2726.         else if(err==12) fprintf(stderr,"Error executing the program to '%s' this file\n",av[1] );
  2727.     free(args);
  2728.     return abort ? !err : err;
  2729. }
  2730.  
  2731.  
  2732.